# -*- coding: iso-8859-1 -*-


"""
Hexagone class - contains everything usefull to manage hexs

Catanyste - Copyright 2008-2009 Julien RAIGNEAU
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance 
with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed 
on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for 
the specific language governing permissions and limitations under the License. 

@author J.Raigneau
"""

import sys, wx
import logging
import math
from gamecomponents import GameComponents
from hexacoordinate import HexaCoordinate

from utils import opj

class Hexagone(object):
    """
    Manages hexagones
    """
    DESERT = GameComponents.DESERT
    LUMBER = GameComponents.LUMBER
    GRAIN = GameComponents.GRAIN
    BRICK = GameComponents.BRICK
    ORE = GameComponents.ORE
    WOOL = GameComponents.WOOL
    SEA = GameComponents.WATER
    DEFAULT = "nada"
    
    """
    wool, grain, brick, ore, lumber
    mouton, ble, argile, minerai, mouton
    """
    
    COLORS = {DESERT:[0, 0, 0],
        LUMBER:[36, 95, 21],
        GRAIN:[241, 252, 46],
        BRICK:[212, 51, 15],
        ORE:[133, 129, 128],
        WOOL:[94, 189, 78],
        SEA:[62, 67, 176],
        DEFAULT:[255, 255, 255]}

    
    PROBA_TAB = {0:0, 2:1, 3:2, 4:3, 5:4, 6:5, 7:6, 8:5, 9:4, 10:3, 11:2, 12:1}

    board = None #ref to hexa's owner ?
    uv = ()
    matiere = DEFAULT
    valeur = 99
    hexacoord = None


    def __init__(self, board, uv, matiere=DEFAULT, valeur=99):
        """
        Inits hex class
        """
        self.board = board
        self.uv = uv # coordonnees sur la grille
        self.matiere = matiere
        self.valeur = valeur
        self.oldFramesize = (0,0)#useful
        self.noeuds = [0,0,0,0,0,0] #aiguille d'une montre noeud1 = en haut à gauche
        
    def PrintClass(self):
        print "%s en (%s,%s) avec la valeur %s et les noeuds {%d,%d,%d,%d,%d,%d}" % (self.matiere, self.uv[0], self.uv[1], self.valeur, self.noeuds[0], self.noeuds[1], self.noeuds[2], self.noeuds[3], self.noeuds[4], self.noeuds[5])


    def CreateHexPath(self, framesize):
        """
        Creates hex path
        """
        if self.oldFramesize == framesize:
            return self.oldPath #should be quicker
        
        #else we do the stuff!
        self.oldFramesize = frameWidth, frameHeight = framesize

        #hexcoord must have been updated by Board
        points = self.hexacoord.getVertexesXYFromUV(self.uv)

        self.oldPath = points

        #useful to knom center of hex
        self.centerX, self.centerY = self.hexacoord.convertUVtoXY(self.uv)
        
        return points
        
    def Draw(self, dc, frameSize):
        """
        Draws hexagone
        """
        try:
            gc = wx.GraphicsContext.Create(dc)
        except NotImplementedError:
            dc.DrawText("This build of wxPython does not support the wx.GraphicsContext "
                "family of classes.",
                25, 25)
            return

#too slow
#        
#        gc.ClipRegion(wx.RegionFromPoints(path)) 
#        bmp = wx.Bitmap(opj('res/%s.jpg' % self.matiere))
#        bsz = bmp.GetSize()
#        x0,y = path[5]
#        x,y0 = path[0]
#        gc.DrawBitmap(bmp,x0,y0,bsz.width, bsz.height)
#        gc.ResetClip()
        path = self.CreateHexPath(frameSize)
        """   #does not work anymore - let's see latter
        if self.matiere != self.SEA:
            x0,y0 = path[0]
            xC, yC = path[3]
        else: #manages cool gradient for sea
            listHex = self.board.listeHexagoneTriee.GetVoisins(self)
            previous = 99
            i = 0
            for hex in listHex:
                if hex != None:
                    if hex.matiere != self.SEA:
                        if previous != 99:
                            if previous < i:
                                i = previous
                            x0,y0 = path[i]
                            if i+3<6:
                                xC, yC = path[i+3]
                            else:
                                xC, yC = path[i-3]
                            break
                        else:
                            previous = i
                            x0,y0 = path[i]
                            if i+3<6:
                                xC, yC = path[i+3]
                            else:
                                xC, yC = path[i-3]

                i = i+1
        """



        r,g,b = self.COLORS[self.matiere]
        oColor = wx.Colour(r,  g,  b, 80)
        cColor = wx.Colour(r,  g,  b, 255)
        gc.SetBrush(gc.CreateLinearGradientBrush(x0, y0, xC, yC, oColor, cColor))
        gc.SetPen(wx.Pen("black", 3))

        gcPath = gc.CreatePath()
        gcPath.MoveToPoint(path[0])
        for i in range(1,6):
            gcPath.AddLineToPoint(path[i])
        gcPath.AddLineToPoint(path[0])
        gc.DrawPath(gcPath)

    #check if thief is on this hex
        uThief, vThief = self.board.GetThief()
        u,v = self.uv
        if u == uThief and v == vThief:
            imageFile = wx.Bitmap(opj('thief.png'))
            dc.DrawBitmap(imageFile, self.centerX-imageFile.GetWidth()/2, self.centerY-imageFile.GetHeight()/2, 1);
        elif self.matiere != self.DESERT and self.matiere != self.SEA and self.valeur != 99:
            s = "%s" % self.valeur
            gc.SetFont(wx.Font(14, wx.SWISS, wx.NORMAL, wx.BOLD))
            width, height = dc.GetTextExtent(s)
            dc.DrawText(s, self.centerX-width/2, self.centerY-height/2 )


    def HitTest(self, p):
        """
            Tests if in hexagon
            The algorithm takes a point and determines if it lies with a polygon by drawing lines through
            the edges of the polygon and checks intersections (odd = in the polygon, even = outside)
            See http://astronomy.swin.edu.au/~pbourke/geometry/insidepoly/
            """
        counter = 0
        N = 6
        xinters = 0.0
        path = self.oldPath
        p1 = path[0]
        for i in range(1,N+1):
            p2 = path[i % N]
            if p[1] > min(p1[1], p2[1]):
                if p[1] <= max(p1[1], p2[1]):
                    if p[0] <= max(p1[0], p2[0]):
                        if p1[1] != p2[1]:
                            xinters = (p[1] - p1[1]) * (p2[0] - p1[0]) / (p2[1] - p1[1]) + p1[0]
                            if p1[0] == p2[0] or p[0] <= xinters:
                                counter=counter+1
            p1 = p2

        if counter % 2 == 0:
            return False
        else:
            return True


class ListHexagone(object):
    """
    Manages hex list
    """
    def __init__(self):
        self.liste = {}
    
    def AddHexagone(self,hex):
        """
        Adds an hex
        """
        u, v = hex.uv
        if self.liste.has_key(u):
            self.liste[u][v] = hex
        else:
            self.liste[u] = {v:hex}
    
    def UpdateHexagone(self, hex):
        """
        Updates an hex
        """
        u, v = hex.uv
        if self.GetHexagone((u, v)):
            self.liste[u][v] = hex
        else:
            print "Hexagone %s", hex.PrintClass()
    
    def PrintClass(self):
        for ligne, colonne in self.liste.iteritems():
            print "-- ligne (%d) --" % ligne
            for ligneBis, colonneBis in colonne.iteritems():
                colonneBis.printClass()      
                        
    def GetHexagone(self, (u, v)):
        """
        Returns hex located in u,v
        """
        #print "je cherche l'hexagone %d %d" % (u,v)
        if self.liste.has_key(u):
            listex = self.liste[u]
            if listex.has_key(v):
                return self.liste[u][v]
            else:
                return None
        else:
            return None
    
    def GetVoisins(self, hex):
        """
        Returns neighbour hex
        """
        u, v = hex.uv

       
        col = u % 2
        col1 = (u + 1) % 2

        #North
        dHex = self.GetHexagone((u, v-1)) #OK
        #North-E
        uHex = self.GetHexagone((u + 1, v-col1))
        #South-East
        ulHex = self.GetHexagone((u + 1, v + col))
        #South
        dlHex = self.GetHexagone((u, v + 1)) #OK
        #South-W
        urHex = self.GetHexagone((u-1, v + col))
        #North-W
        drHex = self.GetHexagone((u-1, v-col1)) #OK
        return [dHex, uHex, ulHex, dlHex, urHex, drHex]

class Thief(object):
    """
    Manages thief
    """
    def __init__(self, uv):
        self.uv = uv
        
    def GetCoord(self):
        """
        returns thief coordinates
        """
        return self.uv
    
    def SetThief(self, hex):
        self.uv=hex.uv